home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / aminet / dev / lang / pcq12src.lzh / Source / Peep.p < prev    next >
Text File  |  1991-04-20  |  17KB  |  757 lines

  1. Program Optimizer;
  2.  
  3. {
  4.     Peep.p from PCQ Pascal
  5.  
  6. Peep is a peephole optimizer that works on the assembly code
  7. produced by PCQ Pascal.  It is not designed to work on any other
  8. code, so be careful.  It reads in the assembly program, optimizes
  9. whatever it can, then writes out a slightly shorter, slightly
  10. faster equivalent file.
  11.  
  12. Peep makes all sorts of assumptions about the source code, one of
  13. which is that the source code is correct.  For example, if an
  14. instruction takes two operands, Peep expects there to be two
  15. operands.  That's O.K. for the compiler output, but you might run
  16. into trouble if you tried using it on normal assembly programs.
  17. It is highly unlikely that anything written in assembly could be
  18. improved by Peep anyway.
  19.  
  20. Using Peep is entirely optional.
  21. }
  22.  
  23.  
  24.  
  25. {$I "Include:Utils/StringLib.i"}
  26. {$I "Include:Utils/Parameters.i"}
  27. {$I "Include:Utils/Break.i"}
  28.  
  29. Const
  30.     MaxPeeps = 199;
  31.  
  32. type
  33.     Operation = (
  34.         op_ADD,
  35.         op_ADDA,
  36.         op_ADDQ,
  37.         op_AND,
  38.         op_ASL,
  39.         op_ASR,
  40.         op_BEQ,
  41.         op_BGE,
  42.         op_BGT,
  43.         op_BLE,
  44.         op_BLT,
  45.         op_BNE,
  46.         op_BPL,
  47.         op_BRA,
  48.         op_BSET,
  49.         op_CLR,
  50.         op_CMP,
  51.         op_CNOP,
  52.         op_DBRA,
  53.         op_DC,
  54.         op_DIVS,
  55.         op_DS,
  56.         op_END,
  57.         op_EOR,
  58.         op_EXG,
  59.         op_EXT,
  60.         op_JSR,
  61.         op_LEA,
  62.         op_LINK,
  63.         op_LSL,
  64.         op_LSR,
  65.         op_MOVE,
  66.         op_MOVEM,
  67.         op_MOVEQ,
  68.         op_MULS,
  69.         op_NEG,
  70.         op_NOT,
  71.         op_OR,
  72.         op_PEA,
  73.         op_RTS,
  74.         op_SECTION,
  75.         op_SEQ,
  76.         op_SGE,
  77.         op_SGT,
  78.         op_SLE,
  79.         op_SLT,
  80.         op_SNE,
  81.         op_SUB,
  82.         op_SUBQ,
  83.         op_SWAP,
  84.         op_TRAP,
  85.         op_TST,
  86.         op_UNLK,
  87.         op_XDEF,
  88.         op_XREF,
  89.         op_None,
  90.         op_LABEL,
  91.         op_EOF);
  92.  
  93.     CodeCell = record
  94.     OpCode    : Operation;
  95.     OSize    : Char;
  96.     Deleted    : Boolean;
  97.     Operand1,
  98.     Operand2,
  99.     Trailer  : String;
  100.     Buffer    : Array [0..127] of Char;
  101.     end;
  102.     CodeCellPtr = ^CodeCell;
  103.  
  104.     PeepArray = Array [0..MaxPeeps] of CodeCell;
  105.  
  106. const
  107.  
  108.     Count   : Array [0..12] of Integer = (0,0,0,0,0,0,0,0,0,0,0,0,0);
  109.  
  110.     Desc    : Array [0..12] of String = (
  111.         "move 0 to clear          ",
  112.         "remove middleman in move ",
  113.         "remove middleadd in add  ",
  114.         "reuse data register      ",
  115.         "don't reload Dn          ",
  116.         "remove 0 test for dest=Dn",
  117.         "remove 0 test for src=Dn ",
  118.         "strip rts trailers       ",
  119.         "remove tst               ",
  120.         "tst, don't move          ",
  121.         "don't and with #255      ",
  122.         "lose test in Scc/Bcc     ",
  123.         "swap beq/bra             ");
  124.  
  125.     OpCodes : Array [op_ADD..op_XREF] of String = (
  126.         "add",
  127.         "adda",
  128.         "addq",
  129.         "and",
  130.         "asl",
  131.         "asr",
  132.         "beq",
  133.         "bge",
  134.         "bgt",
  135.         "ble",
  136.         "blt",
  137.         "bne",
  138.         "bpl",
  139.         "bra",
  140.         "bset",
  141.         "clr",
  142.         "cmp",
  143.         "cnop",
  144.         "dbra",
  145.         "dc",
  146.         "divs",
  147.         "ds",
  148.         "end",
  149.         "eor",
  150.         "exg",
  151.         "ext",
  152.         "jsr",
  153.         "lea",
  154.         "link",
  155.         "lsl",
  156.         "lsr",
  157.         "move",
  158.         "movem",
  159.         "moveq",
  160.         "muls",
  161.         "neg",
  162.         "not",
  163.         "or",
  164.         "pea",
  165.         "rts",
  166.         "section",
  167.         "seq",
  168.         "sge",
  169.         "sgt",
  170.         "sle",
  171.         "slt",
  172.         "sne",
  173.         "sub",
  174.         "subq",
  175.         "swap",
  176.         "trap",
  177.         "tst",
  178.         "unlk",
  179.         "xdef",
  180.         "xref");
  181.  
  182. var
  183.     FirstPeep,
  184.     LastPeep    : Integer;
  185.     PeepHole    : PeepArray;
  186.     InputLine    : String;
  187.     InputFileName : String;
  188.     InputFile    : Text;
  189.     OutputFileName : String;
  190.     OutputFile    : Text;
  191.     EndOfFile    : Boolean;
  192.     Changed    : Boolean;
  193.  
  194.  
  195.  
  196. Procedure Die(ExitCode : Integer);
  197. begin
  198.     Close(InputFile);
  199.     Close(OutputFile);
  200.     Exit(ExitCode);
  201. end;
  202.  
  203. Procedure FindOperand(var c : CodeCell; SymText : String);
  204.  
  205. {
  206.     This just does a binary chop search of the list of operations
  207. }
  208.  
  209. var
  210.     top,
  211.     middle,
  212.     bottom    : Operation;
  213.     compare    : Short;
  214. begin
  215.     Bottom := op_ADD;
  216.     Top := op_XREF;
  217.  
  218.     compare := strpos(SymText, '.');
  219.     if compare = -1 then
  220.     c.OSize := ' '
  221.     else begin
  222.     c.OSize := SymText[Succ(Compare)];
  223.     SymText[compare] := '\0';
  224.     end;
  225.  
  226.     while Bottom <= Top do begin
  227.     middle := Operation((Byte(bottom) + Byte(top)) shr 1);
  228.     Compare := stricmp(OpCodes[Middle], SymText);
  229.     if Compare = 0 then begin
  230.         c.Opcode := Middle;
  231.         return;
  232.     end else if Compare < 0 then
  233.         Bottom := Succ(Middle)
  234.     else
  235.         Top := Pred(Middle);
  236.     end;
  237.     Writeln('Unknown instruction "', SymText, '"');
  238.     Die(10);
  239. end;
  240.  
  241. Procedure ReadWord(InLine : String; var pos : Integer;
  242.             var dest : String; delim : Char);
  243. begin
  244.     while isspace(InLine[pos]) do
  245.     Inc(pos);
  246.     dest := Adr(Inline[pos]);
  247.     while (not isspace(Inline[pos])) and
  248.       (Inline[pos] <> '\0') and
  249.       (Inline[pos] <> delim) do
  250.     Inc(pos);
  251.     Inline[pos] := '\0';
  252.     Inc(pos);
  253. end;
  254.  
  255. Procedure ReadInstruction(var c : CodeCell);
  256. var
  257.     OpStorage : String;
  258.     Leave     : Boolean;
  259.     InputPos,
  260.     LastPos   : Integer;
  261. begin
  262.     with c do begin
  263.     OpCode := op_NONE;
  264.     OSize  := ' ';
  265.     Deleted:= False;
  266.     Operand1 := "";
  267.     Operand2 := "";
  268.     Trailer  := "";
  269.     InputLine := Adr(c.Buffer);
  270.     end;
  271.     repeat
  272.     Leave := True;
  273.     repeat
  274.         if eof(InputFile) then begin
  275.         c.OpCode := op_EOF;
  276.         return;
  277.         end;
  278.         ReadLn(InputFile, InputLine);
  279.     until (strlen(InputLine) > 0) and (InputLine[0] <> '*');
  280.  
  281.     if isspace(InputLine[0]) then begin { It's not a label }
  282.         InputPos := 0;
  283.         ReadWord(InputLine, InputPos, OpStorage, '\0');
  284.         if strlen(OpStorage) > 0 then begin
  285.         FindOperand(c, OpStorage);
  286.         case c.OpCode of
  287.           op_ADD..op_ASR,
  288.           op_BSET,op_CMP..op_DBRA,
  289.           op_DIVS,op_EOR,op_EXG,
  290.           op_LEA..op_MULS,
  291.           op_OR, op_SUB, OP_SUBQ :
  292.             begin
  293.                 ReadWord(InputLine, InputPos, c.Operand1, ',');
  294.                 ReadWord(InputLine, InputPos, c.Operand2, '\0');
  295.             end;
  296.           op_BEQ..op_BRA,op_CLR,
  297.           op_EXT,op_JSR,
  298.           op_NEG,op_NOT,op_PEA,
  299.           op_SECTION..op_SNE,
  300.           op_SWAP..op_UNLK,
  301.           op_XDEF,op_XREF :
  302.             begin
  303.                 ReadWord(InputLine, InputPos, c.Operand1, '\0');
  304.             end;
  305.           op_DC, OP_DS :
  306.             begin
  307.                 while isspace(InputLine[InputPos]) do
  308.                 Inc(InputPos);
  309.                 c.Operand1 := Adr(InputLine[Inputpos]);
  310.             end;
  311.           op_END,op_RTS : ;
  312.         end;
  313.         end else
  314.         Leave := False;
  315.     end else     { It's a label }
  316.         c.OpCode := op_LABEL;
  317.  
  318.     until Leave;
  319. end;
  320.  
  321.  
  322. Procedure FillPeepholeArray;
  323. var
  324.     WasLabel : Boolean;
  325. begin
  326.     LastPeep := 0;
  327.     FirstPeep := 0;
  328.     repeat
  329.     ReadInstruction(PeepHole[LastPeep]);
  330.     WasLabel := PeepHole[LastPeep].OpCode = op_LABEL;
  331.     Inc(LastPeep);
  332.     until WasLabel or (LastPeep > MaxPeeps) or (EOF(InputFile));
  333. end;
  334.  
  335.  
  336. Procedure WriteInstruction(CellNum : Integer);
  337. begin
  338.     with PeepHole[CellNum] do begin
  339.  
  340.     if OpCode = op_EOF then
  341.         return;
  342.  
  343.     if Deleted then
  344.         return;
  345.  
  346.     if OpCode = op_LABEL then begin
  347.         Writeln(OutputFile, String(Adr(Buffer)));
  348.         return;
  349.     end;
  350.  
  351.     Write(OutputFile, '\t', OpCodes[OpCode]);
  352.  
  353.     if OSize <> ' ' then
  354.         write(OutputFile, '.', OSize);
  355.  
  356.     if strlen(Operand1) > 0 then
  357.         Write(OutputFile, '\t', Operand1);
  358.  
  359.     if strlen(Operand2) > 0 then
  360.         Write(OutputFile, ',', Operand2);
  361.  
  362.     Writeln(OutputFile);
  363.     end;
  364. end;
  365.  
  366. Procedure EmptyPeepholeArray;
  367. var
  368.     i : Integer;
  369. begin
  370.     for i := FirstPeep to Pred(LastPeep) do
  371.     WriteInstruction(i);
  372. end;
  373.  
  374. Function NextInstruction(Current : Integer) : Integer;
  375. begin
  376.     repeat
  377.     Inc(Current);
  378.     if Current > LastPeep then
  379.         NextInstruction := -1;
  380.     until not PeepHole[Current].Deleted;
  381.     NextInstruction := Current;
  382. end;
  383.  
  384. Function IsDataRegister(op : String) : Boolean;
  385. begin
  386.     IsDataRegister := (strlen(op) = 2) and
  387.               (toupper(op[0]) = 'D') and
  388.               isdigit(op[1]);
  389. end;
  390.  
  391.  
  392. Function IsAddressRegister(op : String) : Boolean;
  393. begin
  394.     IsAddressRegister := ((strlen(op) = 2) and
  395.              (toupper(op[0]) = 'A') and
  396.              isdigit(op[1])) or
  397.              strieq(op, "sp");
  398. end;
  399.  
  400.  
  401. Function IsRegister(op : String) : Boolean;
  402. begin
  403.     IsRegister := (strlen(op) = 2) and
  404.           ((toupper(op[0]) = 'A') or (toupper(op[0]) = 'D')) and
  405.           isdigit(op[1]);
  406. end;
  407.  
  408. {
  409.     Carry out optimizations in a three-instruction window.
  410.     The optimizations are:
  411.  
  412.     scc    Dn
  413.     tst.b    Dn    =>  scc    Dn
  414.     beq    lab        b~cc   lab
  415.  
  416.     scc    Dn
  417.     tst.b    Dn    =>  scc    Dn
  418.     bne    lab     =>  bcc    lab
  419.  
  420.     move.x    ??,Dn
  421.     any.x    ???,Dn    =>  any.x  ???,??  not done - sub and add
  422.     move.x    Dn,??               require one operand to
  423.                        be a register
  424.  
  425.     beq    lab1
  426.     bra    lab2    =>  bne   lab2  (happens in case statements)
  427.     lab1            lab1
  428. }
  429.  
  430. Procedure Optimize3(Op1 : Integer);
  431. var
  432.     Op2, Op3 : Integer;
  433. begin
  434.     if Peephole[Op1].Deleted then
  435.     return;
  436.  
  437.     Op2 := NextInstruction(Op1);
  438.     if Op2 = -1 then
  439.     return;
  440.     Op3 := NextInstruction(Op2);
  441.     if Op3 = -1 then
  442.     return;
  443.  
  444. {    if (Peephole[Op1].OpCode = op_MOVE) and
  445.     (Peephole[Op3].OpCode = op_MOVE) and
  446.     (Peephole[Op1].OSize = Peephole[Op3].OSize) and
  447.     IsDataRegister(Peephole[Op1].Operand2) and
  448.     streq(Peephole[Op1].Operand1,Peephole[Op3].Operand2) and
  449.     streq(Peephole[Op1].Operand2,Peephole[Op3].Operand1) then begin
  450.     case Peephole[Op2].OpCode of
  451.       op_ADD..op_ASR,
  452.       op_CMP,op_DIVS,
  453.       op_EOR,
  454.       op_LSL,op_LSR,
  455.       op_MULS,op_OR,
  456.       op_SUB,op_SUBQ :
  457.         if (Peephole[Op2].OSize = Peephole[Op1].OSize) and
  458.             streq(Peephole[Op2].Operand2,Peephole[Op1].Operand2) then begin
  459.             Peephole[Op2].Operand2 := Peephole[Op1].Operand1;
  460.             Peephole[Op1].Deleted := True;
  461.             Peephole[Op3].Deleted := True;
  462.             Changed := True;
  463.         end;
  464.       op_CLR,op_NEG,
  465.       op_NOT,op_TST :
  466.         if (Peephole[Op2].OSize = Peephole[Op1].OSize) and
  467.             streq(Peephole[Op2].Operand1,Peephole[Op1].Operand2) then begin
  468.             Peephole[Op2].Operand1 := Peephole[Op1].Operand1;
  469.             Peephole[Op1].Deleted := True;
  470.             Peephole[Op3].Deleted := True;
  471.             Changed := True;
  472.         end;
  473.     end;
  474.     end else} if ((Peephole[Op1].OpCode >= op_SEQ) or
  475.         (Peephole[Op1].OpCode <= op_SNE)) and
  476.         IsDataRegister(Peephole[Op1].Operand1) and
  477.         (Peephole[Op2].OpCode = op_TST) and
  478.         streq(Peephole[Op1].Operand1, Peephole[Op2].Operand1) and
  479.         ((Peephole[Op3].OpCode = op_BEQ) or
  480.         (Peephole[Op3].OpCode = op_BNE)) then begin
  481.     if Peephole[Op3].OpCode = op_BEQ then begin
  482.         case Peephole[Op1].OpCode of
  483.           op_SEQ : Peephole[Op3].OpCode := op_BNE;
  484.           op_SGE : Peephole[Op3].OpCode := op_BLT;
  485.           op_SGT : Peephole[Op3].OpCode := op_BLE;
  486.           op_SLE : Peephole[Op3].OpCode := op_BGT;
  487.           op_SLT : Peephole[Op3].OpCode := op_BGE;
  488.           op_SNE : Peephole[Op3].OpCode := op_BEQ;
  489.         end;
  490.     end else begin
  491.         case Peephole[Op1].OpCode of
  492.           op_SEQ : Peephole[Op3].OpCode := op_BEQ;
  493.           op_SGE : Peephole[Op3].OpCode := op_BGE;
  494.           op_SGT : Peephole[Op3].OpCode := op_BGT;
  495.           op_SLE : Peephole[Op3].OpCode := op_BLE;
  496.           op_SLT : Peephole[Op3].OpCode := op_BLT;
  497.           op_SNE : Peephole[Op3].OpCode := op_BNE;
  498.         end;
  499.     end;
  500.     Peephole[Op2].Deleted := True;
  501.     Changed := True; Inc(Count[11]);
  502.     end else if (Peephole[Op1].OpCode = op_BEQ) and
  503.         (Peephole[Op2].OpCode = op_BRA) and
  504.         (Peephole[Op3].OpCode = op_LABEL) and
  505.         streq(Peephole[Op1].Operand1,Adr(Peephole[Op3].Buffer)) then begin
  506.     Peephole[Op2].OpCode := op_BNE;
  507.     Peephole[Op1].Deleted := True;
  508.     Changed := True; Inc(Count[12]);
  509.     end;
  510. end;
  511.  
  512. {
  513.     Carry out optimizations in a two-instruction window.
  514.     The optimizations are:
  515.  
  516.     move.x    ??,Dn
  517.     move.x    Dn,???    =>    move.x    ??,??? (?? <> (a0)+ )
  518.  
  519.     move.x    ??,Dn
  520.     add.x    Dn,???    =>    add.l    ??,???
  521.  
  522.     move.x    Dn,???
  523.     move.x    ???,Dn    =>    move.x    Dn,???
  524.  
  525.     move.x    Dn,???        move.x    Dn,???
  526.     move.x    ???,??    =>    move.x    Dn,??
  527.  
  528.     any.x    ??,Dn
  529.     cmp.x    #0,Dn    =>    any.x    ??,Dn
  530.  
  531.     move.x    Dn,??
  532.     cmp.x    #0,Dn    =>    move.x    Dn,?? (?? <> An)
  533.  
  534.     rts
  535.     anything    =>    rts
  536.  
  537.     any.x    ??,Dn
  538.     tst.x    Dn    =>    any.x    ??,Dn
  539.  
  540.     any.x    Dn
  541.     tst.x    Dn    =>    any.x    Dn
  542.  
  543.     move.x    ??,Dn    =>    tst.x    ??
  544.     scc    Dn        scc    Dn
  545.  
  546.     move.b    #?,Dn
  547.     and.x    #255,Dn    =>    move.x    #?,Dn
  548.  
  549. }
  550.  
  551. Procedure Optimize2(Op1 : Integer);
  552. var
  553.     Op2 : Integer;
  554. begin
  555.     if Peephole[Op1].deleted then
  556.     return;
  557.  
  558.     Op2 := NextInstruction(Op1);
  559.     if Op2 = -1 then
  560.     return;
  561.  
  562.     if (Peephole[Op1].OpCode = op_MOVE) and
  563.     (Peephole[Op2].OpCode = op_MOVE) and
  564.     (Peephole[Op1].OSize = Peephole[Op2].OSize) then begin
  565.  
  566.     if IsDataRegister(Peephole[Op1].Operand1) and
  567.        streq(Peephole[Op1].Operand2,Peephole[Op2].Operand1) then begin
  568.  
  569.         if streq(Peephole[Op1].Operand1,Peephole[Op2].Operand2) then begin
  570.         Peephole[Op2].Deleted := True; Inc(Count[4]);
  571.         end else begin
  572.         Peephole[Op2].Operand1 := Peephole[Op1].Operand1; Inc(Count[3]);
  573.         end;
  574.         Changed := True;
  575.     end else if IsRegister(Peephole[Op1].Operand2) and
  576.         streq(Peephole[Op1].Operand2,Peephole[Op2].Operand1) and
  577.         (not streq(Peephole[Op1].Operand1,"(a0)+")) and
  578.         (not IsRegister(Peephole[Op2].Operand2)) then begin
  579.         Peephole[Op1].Operand2 := Peephole[Op2].Operand2;
  580.         Peephole[Op2].Deleted := True;
  581.         Changed := True;
  582.         Inc(Count[1]);
  583.     end;
  584.     end else if Peephole[Op1].OpCode = op_RTS then begin
  585.     case Peephole[Op2].OpCode of
  586.       op_ADD..op_CMP,
  587.       op_DBRA,op_DIVS,
  588.       op_EOR..op_RTS,
  589.       op_SEQ..op_UNLK : begin
  590.                 Peephole[Op2].Deleted := True;
  591.                 Changed := True;
  592.                 Inc(Count[7]);
  593.                 end;
  594.     end;
  595.     end else if (Peephole[Op2].OpCode = op_CMP) and
  596.         (streq(Peephole[Op2].Operand1,"#0") or
  597.          streq(Peephole[Op2].Operand1, "#$0")) and
  598.         IsDataRegister(Peephole[Op2].Operand2) then begin
  599.     case Peephole[Op1].OpCode of
  600.       op_NEG,op_NOT,op_EXT :
  601.         if streq(Peephole[Op1].Operand1,Peephole[Op2].Operand2) and
  602.             (Peephole[Op1].OSize = Peephole[Op2].OSize) then begin
  603.             Peephole[Op2].Deleted := True;
  604.             Changed := True;
  605.             Inc(Count[5]);
  606.         end;
  607.       op_ADD,op_ADDQ,op_AND,
  608.       op_ASL,op_ASR,op_DIVS,op_EOR,
  609.       op_EXG,op_LSL,op_LSR,
  610.       op_MULS,op_OR,
  611.       op_SUB,op_SUBQ :
  612.         if streq(Peephole[Op1].Operand2,Peephole[Op2].Operand2) and
  613.             (Peephole[Op1].OSize = Peephole[Op2].OSize) then begin
  614.             Peephole[Op2].Deleted := True;
  615.             Changed := True; Inc(Count[5]);
  616.         end;
  617.       op_MOVE, op_MOVEQ :
  618.         if streq(Peephole[Op1].Operand2,Peephole[Op2].Operand2) and
  619.             (Peephole[Op1].OSize = Peephole[Op2].OSize) then begin
  620.             Peephole[Op2].Deleted := True;
  621.             Changed := True;
  622.             Inc(Count[5]);
  623.         end else if streq(Peephole[Op1].Operand1,Peephole[Op2].Operand2) and
  624.             (Peephole[Op1].OSize = Peephole[Op2].OSize) and
  625.             (not IsAddressRegister(Peephole[Op1].Operand1)) then begin
  626.             Peephole[Op2].Deleted := True;
  627.             Changed := True; Inc(Count[6]);
  628.         end;
  629.     end;
  630.     end else if (Peephole[Op2].OpCode = op_TST) and
  631.         IsDataRegister(Peephole[Op2].Operand1) then begin
  632.     case Peephole[Op1].OpCode of
  633.       op_NEG,op_NOT,op_EXT :
  634.         if streq(Peephole[Op1].Operand1,Peephole[Op2].Operand1) and
  635.             (Peephole[Op1].OSize = Peephole[Op2].OSize) then begin
  636.             Peephole[Op2].Deleted := True;
  637.             Changed := True;
  638.             Inc(Count[8]);
  639.         end;
  640.       op_ADD,op_ADDQ,op_AND,
  641.       op_ASL,op_ASR,op_DIVS,op_EOR,
  642.       op_EXG,op_LSL,op_LSR,
  643.       op_MOVE,op_MOVEQ,op_MULS,
  644.       op_OR,op_SUB,op_SUBQ :
  645.         if streq(Peephole[Op1].Operand2,Peephole[Op2].Operand1) and
  646.             (Peephole[Op1].OSize = Peephole[Op2].OSize) then begin
  647.             Peephole[Op2].Deleted := True;
  648.             Changed := True;
  649.             Inc(Count[8]);
  650.         end;
  651.     end;
  652.     end else if (Peephole[Op1].OpCode = op_MOVE) and
  653.         (Peephole[Op2].OpCode >= op_SEQ) and
  654.         (Peephole[Op2].OpCode <= op_SNE) and
  655.         streq(Peephole[Op1].Operand2,Peephole[Op2].Operand1) then begin
  656.     with Peephole[Op1] do begin
  657.         OpCode := op_TST;
  658.         Operand2 := "";
  659.     end;
  660.     Inc(Count[9]);
  661.     Changed := True;
  662.     end else if (Peephole[Op1].OpCode = op_MOVE) and
  663.         (Peephole[Op1].Operand1[0] = '#') and
  664.         (Peephole[Op2].OpCode = op_AND) and
  665.         streq(Peephole[Op2].Operand1,"#255") and
  666.         IsDataRegister(Peephole[Op1].Operand2) and
  667.         streq(Peephole[Op1].Operand2,Peephole[Op2].Operand2) and
  668.         (Peephole[Op1].OSize = 'b') then begin
  669.     Peephole[Op1].OSize := Peephole[Op2].OSize;
  670.     Peephole[Op2].Deleted := True;
  671.     Changed := True;
  672.     Inc(Count[10]);
  673. {    end else if (Peephole[Op1].OpCode = op_MOVE) and
  674.         (Peephole[Op2].OpCode = op_CMP) and
  675.         IsDataRegister(Peephole[Op1].Operand2) and
  676.         streq(Peephole[Op1].Operand2,Peephole[Op2].Operand2) and
  677.         (Peephole[Op2].Operand1[0] = '#') and
  678.         (Peephole[Op1].OSize = Peephole[Op2].OSize) then begin
  679.     Peephole[Op2].Operand2 := Peephole[Op1].Operand1;
  680.     Peephole[Op1].Deleted := True;
  681.     Changed := True; }
  682.     end;
  683. end;
  684.  
  685. {
  686.     Carry out optimizations in a one-instruction window.
  687.     The optimizations are:
  688.  
  689.     move.x    #0,??    =>    clr.x ?? (if x <> l and ?? <> Dn )
  690. }
  691.  
  692. Procedure Optimize1(Op : Integer);
  693. begin
  694.     if Peephole[Op].Deleted then
  695.     return;
  696.  
  697.     with Peephole[Op] do begin
  698.     if (OpCode = op_MOVE) and
  699.        (streq(Operand1, "#0") or streq(Operand1, "#$0")) and
  700.        ((not IsDataRegister(Operand2)) or (OSize <> 'l')) then begin
  701.         Operand1 := Operand2;
  702.         Operand2 := "";
  703.         OpCode := op_CLR;
  704.         Changed := True;
  705.         Inc(Count[0]);
  706.     end;
  707.     end;
  708. end;
  709.  
  710. var
  711.     i : Integer;
  712. begin
  713.     Writeln('PCQ Peephole optimizer');
  714.  
  715.     InputFileName := AllocString(256);
  716.     OutputFileName := AllocString(256);
  717.  
  718.     GetParam(1,InputFileName);
  719.     GetParam(2,OutputFileName);
  720.  
  721.     if (strlen(InputfileName) <= 0) or 
  722.        (strlen(OutputFileName) <= 0) then begin
  723.     Writeln('Usage: Optimize filename');
  724.     Exit(20);
  725.     end;
  726.  
  727.     FirstPeep := 0;
  728.     LastPeep  := 0;
  729.  
  730.     if not open(OutputFileName, OutputFile) then begin
  731.     Writeln('Could not open output file: ', OutputFileName);
  732.     Exit(10);
  733.     end;
  734.  
  735.     if reopen(InputFileName, InputFile) then begin
  736.     while not eof(InputFile) do begin
  737.         FillPeepholeArray;
  738.         repeat
  739.         Changed := False;
  740.         for i := FirstPeep to LastPeep do begin
  741.             Optimize3(i);
  742.             Optimize2(i);
  743.             Optimize1(i);
  744.         end;
  745.         if CheckBreak then
  746.             Die(20);
  747.         until not Changed;
  748.         EmptyPeepholeArray;
  749.     end;
  750.  
  751.     for i := 0 to 12 do
  752.         Writeln(Desc[i], ':', Count[i]);
  753.  
  754.     Die(0);
  755.     end;
  756. end.
  757.